package controllers

import (
	"encoding/json"
	"github.com/pkg/errors"
	"github.com/spf13/cast"
	"nft-server/common"
	"nft-server/errcode"
	"nft-server/logger"
	"nft-server/service"
)

const (
	UserURI                    = "/v1/admin/user"
	LockUserURI                = "/v1/admin/user/lock"
	UnLockUserURI              = "/v1/admin/user/unlock"
	GetUsersByNameAndStatusURI = "/v1/admin/userlist"
)

type AdminController struct {
	CommonController
}

func (nc *AdminController) GetUserById() {
	userId := nc.Ctx.Input.Query("userid")
	user, err := service.GetUserById(cast.ToInt(userId))
	if err != nil {
		nc.HandleErrCode(errcode.E.Base.RequestInvalid.WithErr(err))
		return
	}
	if user == nil {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("查询的用户不存在"))
		return
	}
	nc.HandleBusinessObj(user)
}
func (nc *AdminController) DeleteUserById() {
	userId := nc.Ctx.Input.Query("userid")

	if len(userId) == 0 {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("用户ID为空"))
		return
	}
	user, err := service.GetUserById(cast.ToInt(userId))
	if err != nil {
		nc.HandleErrCode(errcode.E.Internal.Internal.WithErr(err))
		return
	}
	if user == nil {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("删除的用户不存在"))
		return
	}

	adminIdSession := nc.GetSession(common.SessionUserId)
	if adminIdSession == nil {
		logger.Error("Failed to get user name from session id")
		nc.HandleErrCode(errcode.E.Certification.HavaNotLogin)
		return

	}
	adminId, ok := adminIdSession.(int)
	if !ok {
		logger.Error("DeleteUserById Assert_Error.")
		nc.HandleErrCode(errcode.E.Internal.Internal)
		return
	}
	if cast.ToInt(userId) == adminId {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("管理员不能删除自己！"))
		return
	}
	err = service.DeleteUserById(cast.ToInt(userId))
	if err != nil {
		logger.Error("DeleteUserById: %v", err)
		nc.HandleErrCode(errcode.E.Internal.Internal.WithErr(err))
		return
	}
	nc.HandleBusinessSuccess()
}
func (nc *AdminController) LockUser() {
	req := common.LockAndUnlockUserReq{}
	if err := json.Unmarshal(nc.Ctx.Input.RequestBody, &req); err != nil {
		logger.Error("LockUserReq Unmarshal error: %v", err)
		nc.HandleErrCode(errcode.E.Base.RequestInvalid.WithErr(err))
		return
	}

	adminIdSession := nc.GetSession(common.SessionUserId)
	if adminIdSession == nil {
		logger.Error("Failed to get user name from session id")
		nc.HandleErrCode(errcode.E.Certification.HavaNotLogin)
		return

	}
	adminId, ok := adminIdSession.(int)
	if !ok {
		logger.Error("LockUser Assert_Error.")
		nc.HandleErrCode(errcode.E.Internal.Internal)
		return
	}
	if req.UserId == adminId {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("管理员不能锁定自己！"))
		return
	}

	user, err := service.GetUserById(req.UserId)
	if err != nil {
		nc.HandleErrCode(errcode.E.Internal.Internal.WithErr(err))
		return
	}
	if user == nil {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("锁定的用户不存在"))
		return
	}

	user, err = service.UpdateLockedById(req.UserId, true)
	if err != nil {
		logger.Error("LockUser: %v", err)
		nc.HandleErrCode(errcode.E.Base.RequestInvalid.WithErr(err))
		return
	}
	nc.HandleBusinessObj(user)
}
func (nc *AdminController) UnlockUser() {

	req := common.LockAndUnlockUserReq{}
	if err := json.Unmarshal(nc.Ctx.Input.RequestBody, &req); err != nil {
		logger.Error("UnLockUserReq Unmarshal error: %v", err)
		nc.HandleErrCode(errcode.E.Base.RequestInvalid.WithErr(err))
		return
	}
	user, err := service.GetUserById(req.UserId)
	if err != nil {
		nc.HandleErrCode(errcode.E.Internal.Internal.WithErr(err))
		return
	}
	if user == nil {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("解锁的用户不存在"))
		return
	}

	user, err = service.UpdateLockedById(req.UserId, false)
	if err != nil {
		logger.Error("UnLockUser: %v", err)
		nc.HandleErrCode(errcode.E.Base.RequestInvalid.WithErr(err))
		return
	}
	nc.HandleBusinessObj(user)
}

//GetUsersByNameAndStatus 根据用户名和锁定状态进行查询
func (nc *AdminController) GetUsersByNameAndStatus() {
	userName := nc.Ctx.Input.Query("username")
	locked := nc.Ctx.Input.Query("locked")
	pageNum := cast.ToInt(nc.Ctx.Input.Query("pagenum"))
	pageSize := cast.ToInt(nc.Ctx.Input.Query("pagesize"))
	if pageSize <= 0 || pageNum <= 0 {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("页码和每页数量必须大于0"))
		return
	}
	totalNum, err := nc.getTotalNumByNameAndStatus(pageNum, pageSize, userName, locked)
	if err != nil {
		return
	}
	totalPageNum := totalNum / pageSize
	if totalNum%pageSize != 0 {
		totalPageNum++
	}
	if pageNum > totalPageNum {
		nc.HandleErrCode(errcode.E.Base.ErrorMessage.WithMessage("页码不能大于总页码数"))
		return
	}
	if err != nil {
		nc.HandleErrCode(errcode.E.Internal.Internal.WithErr(err))
		return
	}
	users, err := nc.getUsersByNameAndStatus(pageNum, pageSize, userName, locked)
	if err != nil {
		return
	}
	userList := &common.UserList{
		PageNum:      pageNum,
		PageSize:     pageSize,
		TotalPageNum: totalPageNum,
		TotalNum:     totalNum,
		UserList:     users,
	}
	nc.HandleBusinessObj(userList)
}

func (nc *AdminController) getTotalNumByNameAndStatus(pageNum, pageSize int, userName, locked string) (totalNum int, err error) {
	if len(userName) == 0 && len(locked) == 0 {
		totalNum, err = service.GetUserNum()
	} else if len(userName) != 0 && len(locked) == 0 {
		totalNum, err = service.GetUserNumByMatchingName(userName)
	} else if len(userName) == 0 && len(locked) != 0 {
		totalNum, err = service.GetUserNumByStatus(cast.ToBool(locked))
	} else {
		totalNum, err = service.GetUserNumByNameAndStatus(userName, cast.ToBool(locked))
	}
	if err != nil {
		logger.Error("getTotalNumByNameAndStatus error: %v", err)
		nc.HandleErrCode(errcode.E.Internal.Internal.WithErr(err))
		return 0, errors.New("getTotalNumByNameAndStatus error")
	}
	if totalNum == 0 {
		userList := &common.UserList{
			PageNum:      pageNum,
			PageSize:     pageSize,
			TotalPageNum: 0,
			TotalNum:     0,
			UserList:     nil,
		}
		nc.HandleBusinessObj(userList)
		return totalNum, errors.New("totalNum is zero")
	}
	return totalNum, nil
}

func (nc *AdminController) getUsersByNameAndStatus(pageNum, pageSize int, userName, locked string) (users []*common.User, err error) {
	if len(userName) == 0 && len(locked) == 0 {
		users, err = service.GetUsers(pageSize, pageNum)
	} else if len(userName) != 0 && len(locked) == 0 {
		users, err = service.GetUsersByMatchingName(userName, pageNum, pageSize)
	} else if len(userName) == 0 && len(locked) != 0 {
		users, err = service.GetUsersByStatus(cast.ToBool(locked), pageNum, pageSize)
	} else {
		users, err = service.GetUsersByNameAndStatus(userName, cast.ToBool(locked), pageNum, pageSize)
	}
	if err != nil {
		logger.Error("getUsersByNameAndStatus error: %v", err)
		nc.HandleErrCode(errcode.E.Internal.Internal.WithErr(err))
		return nil, errors.New("getUsersByNameAndStatus error")
	}
	return users, nil
}
